/*
	Reads from markers.uts (default location is C:\Temp\), and outputs a file
	for use by the NGramAnalyzer (default filename: C:\Temp\output.txt).
*/

////////////////////////////////////////
// Namespace
////////////////////////////////////////

using namespace std;



////////////////////////////////////////
// Include files
////////////////////////////////////////

#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <string.h>
#include <math.h>
#include <ctype.h>
#include <vector>
#include "../RTreeTemplate/RTree.h"

////////////////////////////////////////
// Constant definitions
////////////////////////////////////////

// UTM offsets 
double utm_x_offset = 444965;
double utm_y_offset = 5029450;



////////////////////////////////////////
// Type definitions
////////////////////////////////////////

typedef enum {
  POINT_MARKER,
  LINE_MARKER,
  AREA_MARKER 
} MarkerShape;


struct Point {
  public:
    Point(void) : x(0), y(0), z(0) {};
  public:
    double x, y, z;
};


struct Marker {
  public:
    Marker(void) : shape(POINT_MARKER), points(), radius(0)
      { identifier[0] = '\0'; name[0] = '\0'; };
  public:
    MarkerShape shape;
    char identifier[64];
    char name[256];
    vector<Point *> points;
    double radius;
};


struct MarkerSet {
  public:
    MarkerSet(void) : markers() {};
    int Read(const char *filename);
    int Print(void);
    typedef std::vector<Marker *>::iterator iterator;
    typedef std::vector<Marker *>::const_iterator const_iterator;

   public:
    vector<Marker *> markers;    
};



////////////////////////////////////////
// I/O function
////////////////////////////////////////

int MarkerSet::
Read(const char *filename)
{
  // Open file
  FILE *fp = fopen(filename, "r");
  if (!fp) {
    fprintf(stderr, "Unable to open file: %s\n", filename);
	getchar();
    return 0;
  }

  // Read file
  int line_count = 0;
  char buffer[1024];
  Marker *marker = NULL;
  while (fgets(buffer, 1024, fp)) {
    line_count++;
    if (!strncmp(buffer, "STARTPOINT", 10)) {
      // Create point marker
      marker = new Marker();
      marker->shape = POINT_MARKER;
      markers.push_back(marker);
    }
    else if (!strncmp(buffer, "STARTLINE", 9)) {
      // Create line marker
      marker = new Marker();
      marker->shape = LINE_MARKER;
      markers.push_back(marker);
    }
    else if (!strncmp(buffer, "STARTAREA", 9)) {
      // Create area marker
      marker = new Marker();
      marker->shape = AREA_MARKER;
      markers.push_back(marker);
    }
    else if (!strncmp(buffer, "ENDPOINT", 8)) {
      // Reset marker
      marker = NULL;
    }
    else if (!strncmp(buffer, "ENDLINE", 7)) { 
      // Reset marker
      marker = NULL;
    }
    else if (!strncmp(buffer, "ENDAREA", 7)) {
      // Reset marker
      marker = NULL;
    }
    else if (marker) {
      // Parse marker fields
      if (!strncmp(buffer, "IDENTIFIER", 10)) {
        char *startp = &buffer[10];
        while ((*startp != '\0') && (isspace(*startp))) startp++;
        char *endp = startp;
        while ((*endp != '\0') && (!isspace(*endp))) endp++;
        *endp = '\0';
        strncpy(marker->identifier, startp, 64);
        startp = endp + 1;
        while ((*startp != '\0') && (isspace(*startp))) startp++;
        endp = startp;
        while ((*endp != '\0') && (*endp != '\n')) endp++;
        *endp = '\0';
        strncpy(marker->name, startp, 256);
      }
      else if (!strncmp(buffer, "POINTRADIUS", 11)) {
        char POINTRADIUS[64];
        if ((sscanf(buffer, "%s%lf", POINTRADIUS, &marker->radius) != 2) || strcmp(POINTRADIUS, "POINTRADIUS")) {
          fprintf(stderr, "Error parsing line %d in %s\n", line_count, filename);
          return 0;
        }
      }
      else if (!strncmp(buffer, "LINEHALFWIDTH", 13)) {
        char LINEHALFWIDTH[64];
        if ((sscanf(buffer, "%s%lf", LINEHALFWIDTH, &marker->radius) != 2) || strcmp(LINEHALFWIDTH, "LINEHALFWIDTH")) {
          fprintf(stderr, "Error parsing line %d in %s\n", line_count, filename);
          return 0;
        }
      }
      else if (!strncmp(buffer, "X ", 2)) {
        // Parse point coordinates
        double x, y, z;
        char X[64], Y[64], Z[64];
        if ((sscanf(buffer, "%s%lf%s%lf%s%lf", X, &x, Y, &y, Z, &z) != 6) ||
            (strcmp(X, "X") || strcmp(Y, "Y") || strcmp(Z, "Z"))) {
          fprintf(stderr, "Error parsing line %d in %s\n", line_count, filename);
          return 0;
        }

        // Create a point
        Point *point = new Point();
        marker->points.push_back(point);

        // Set point coordinates (offset by UTM origin)
        point->x = x - utm_x_offset; 
        point->y = y - utm_y_offset; 
        point->z = z;
      }
    }
  }

  // Close file
  fclose(fp);

  // Return success
  return 1;
}


int MarkerSet::
Print(void)
{
  // Open file
  char *filename = "C:\\Temp\\output.txt";
  FILE *fp = fopen(filename, "w");
  if (!fp) {
    fprintf(stderr, "Unable to open file: %s\n", filename);
	getchar();
    return 0;
  }


  // Print info about markers
  for (MarkerSet::iterator iter = markers.begin(); iter != markers.end(); iter++) {
    Marker *marker = *iter;
    fprintf(fp, "Label:\t%s\n", marker->name);
    for (unsigned int i = 0; i < marker->points.size(); i++) {
      Point *point = marker->points[i];
      fprintf(fp, "Coords:\t%.6f\t%.6f\t%.6f\n", point->x, point->y, point->z);
    }
  }

  // Close file
  fclose(fp);

  return 1;
}


////////////////////////////////////////
// Main
////////////////////////////////////////

int 
main(int argc, char **argv)
{
  //// Print usage if no arguments
  //if (argc < 2) {
  //  fprintf(stderr, "Usage: printmarkers utsfile\n");
  //  exit(-1);
  //}

  // Get filename
  char *uts_name = "C:\\Temp\\markers.uts";
  //char *uts_name = argv[1];

  // Read marker set
  MarkerSet *markerset = new MarkerSet();
  if (!markerset->Read(uts_name)) exit(-1);

  
  // Print marker set
  if (!markerset->Print()) exit(-1);

  printf("Done.\n");
  getchar();
}
